import { ref } from "vue";
import { http, type ErrInfo } from "./base";

async function createUuid() {
    const resp = await http.get('/uuid');
    return await resp.parse<string>();
}

const TOKEN_KEY = "token-key";

export async function getToken() {
    const item = localStorage.getItem(TOKEN_KEY);
    if (item != null) {
        return item;
    }
    const uuid = await createUuid();
    localStorage.setItem(TOKEN_KEY, uuid);
    return uuid;
}

// async function getVoteLatestId() {
//     const resp = await http.get('/vote/latest_id');
//     return await resp.parse<number>();
// }


const EC_WAIT_TIMEOUT = 1;
const EC_UNKNOWN = 2;
const EC_ALREADY_VOTE = 3;

export const VOTE_ROOM = 0;
export const VOTE_POS = 1;
export const VOTE_NEG = 2;
export const VOTE_ONLINE = 3;

export async function online() {
    try {
        await vote_impl(VOTE_ONLINE);
    } catch (err) {
        if (err instanceof Object) {
            const info = err as ErrInfo;
            if (info.ec != EC_ALREADY_VOTE) {
                throw info.msg;
            }
        } else {
            throw err;
        }
    }
}

async function vote_impl(ty: number) {
    const token = await getToken();
    const vote_id = await current_id();
    const req = {
        ty,
        token,
        vote_id,
    };
    await http.post({
        url: '/vote_num/create',
        body: req,
    });
}

export async function vote(ty: number) {
    try {
        await vote_impl(ty);
    } catch (err) {
        if (err instanceof Object) {
            const info = err as ErrInfo;
            throw info.msg;
        } else {
            throw err;
        }
    }
}

export async function get_vote_count(ty: number) {
    let vote_id = await current_id();
    const resp = await http.get(`/vote_num/count?vote_id=${vote_id}&ty=${ty}`);
    return await resp.parse<number>();
}

export async function get_vote_count_with_vote_id(vote_id: number, ty: number) {
    const resp = await http.get(`/vote_num/count?vote_id=${vote_id}&ty=${ty}`);
    return await resp.parse<number>();
}

export async function vote_create(name: string) {
    await http.post({
        url: '/vote/create',
        body: name
    });
}

export async function current_id() {

    try {
        const resp = await http.get('/vote/current_id');
        return await resp.parse<number>();
    } catch (err) {
        if (err instanceof Object) {
            const info = err as ErrInfo;
            throw info.msg;
        } else {
            throw err;
        }
    }
}

export async function set_current(id: number) {
    try {
        await http.post({
            url: '/vote/set_current',
            body: id
        });
    } catch (err) {
        if (err instanceof Object) {
            const info = err as ErrInfo;
            throw info.msg;
        } else {
            throw err;
        }
    }
}

export async function query_vote_id() {
    const resp = await http.get('/vote_num/vote_id');
    return resp.parse<number[]>();
}

export interface VoteInfo {
    vote_id: number,
    pos: number,
    neg: number,
}

export async function query_vote_info() {
    const votes = await query_vote_id();
    const infos: VoteInfo[] = [];
    for (const id of votes) {
        const pos = await get_vote_count_with_vote_id(id, VOTE_POS);
        const neg = await get_vote_count_with_vote_id(id, VOTE_NEG);
        infos.push({
            vote_id: id,
            pos,
            neg,
        });
    }
    return infos;
}

export interface Info {
    online: number,
    room: number,
    debate_positive: number,
    debate_negative: number,
}

async function wait() {
    try {
        const resp = await http.get('/wait');
        await resp.body();
        return true;
    } catch (e) {
        if (e instanceof Object) {
            const errInfo = e as ErrInfo;
            if (errInfo.ec == EC_WAIT_TIMEOUT) {
                return false;
            } else {
                throw errInfo.msg
            }
        } else {
            throw e;
        }
    }
}

export const updateFlag = ref(0);

export async function wait_update_loop() {
    while (true) {
        const ret = await wait();
        if (!ret) {
            continue;
        }
        updateFlag.value += 1;
    }
}


